﻿using System;
using System.Collections.Generic;
using System.IO;

namespace Utilities.Settings {
    class cSettingsOrganizer {
        private bool flag_AutoSave;
        private bool flag_AutoSaveAvailable;
        private bool flag_LoadedFromFile;
        private bool flag_ChangedSinceLoad;
        private bool flag_ChangedSinceSave;

        private string memory_LoadedFile;
        private string[] memory_LastSettingQuery;

        private List<string[]> lList;

        // ####################################################
        // #####    Object Initialization
        // ####################################################
        #region Object Initialization

        public cSettingsOrganizer() {
            do_Initialize();
            do_Preset();
            do_Startup();
        }

        ~cSettingsOrganizer() {
            do_Finalize();
        }

        private void do_Initialize() {
            lList = new List<string[]>();
        }

        private void do_Preset() {
            flag_AutoSave = false;
            flag_AutoSaveAvailable = false;
            flag_LoadedFromFile = false;
            flag_ChangedSinceLoad = false;
            flag_ChangedSinceSave = false;

            memory_LoadedFile = null;
            memory_LastSettingQuery = null;
        }

        private void do_Startup() {

        }

        private void do_Finalize() {
            if (flag_AutoSaveAvailable && flag_AutoSave && flag_ChangedSinceSave) {
                do_Settings_Save(memory_LoadedFile);
            }
        }

        #endregion

        // ####################################################
        // #####    Public Access
        // ####################################################
        #region Public Access

        public void Flag_Set_AutoSave(Boolean bFlag) {
            flag_AutoSave = bFlag;
        }

        public Boolean Flag_Get_AutoSave() {
            return flag_AutoSave;
        }

        public Boolean Flag_Get_LoadedFromFile() {
            return flag_LoadedFromFile;
        }

        public Boolean Flag_Get_ChangedSinceLoad() {
            return flag_ChangedSinceLoad;
        }

        public Boolean Flag_Get_ChangedSinceSave() {
            return flag_ChangedSinceSave;
        }

        public bool Settings_Load(string sFilename) {
            return do_Settings_Load(sFilename);
        }

        public bool Settings_Save(string sFilename) {
            return do_Settings_Save(sFilename);
        }

        public bool Settings_AutoSave() {
            if (flag_AutoSaveAvailable) {
                return do_Settings_Save(memory_LoadedFile);
            }
            else {
                return false;
            }
        }

        public bool Setting_Set(string sName, string sValue) {
            return do_Setting_Set(sName, sValue);
        }

        public bool Setting_Set_IfNotExist(string sName, string sValue) {
            if (do_Setting_Get(sName) == null) { return do_Setting_Set(sName, sValue); }
            else { return false; }
        }

        public string Setting_Get(string sName) {
            return do_Setting_Get(sName);
        }

        public bool Setting_Delete(string sName) {
            return do_Setting_Delete(sName);
        }

        #endregion

        // ####################################################
        // #####    Private Functions
        // ####################################################
        #region Private Functions

        private bool do_Settings_Load(string sFilename) {
            FileInfo oFInfo;
            FileStream oStream;
            StreamReader oReader;
            string[] sLines;
            string[] sSplit;
            string sTemp;

            if (sFilename == null) { // load standard 
                sFilename = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6);
            }
            flag_AutoSaveAvailable = true;
            memory_LoadedFile = sFilename;
            oFInfo = new FileInfo(sFilename);
            if (oFInfo.Exists) {
                oStream = new FileStream(sFilename, FileMode.Open);
                oReader = new StreamReader(oStream);
                sTemp = oReader.ReadToEnd();
                oReader.Close();
                oStream.Close();
                if (sTemp != null) {
                    if (sTemp != "") {
                        if (sTemp.Contains("\n")) {
                            // Multiline
                            sLines = sTemp.Split(new char[] { '\n', '\r' });
                        }
                        else {
                            // Singleline
                            sLines = new string[1];
                            sLines[0] = sTemp;
                        }
                        // Clearing list
                        lList.Clear();
                        for (int i = 0; i <= sLines.GetUpperBound(0); i++) {
                            // Check for synthax
                            if (sLines[i].Contains("=")) {
                                sSplit = sLines[i].Split('=');
                                // Add to list
                                lList.Add(new string[] { sSplit[0], sSplit[1] });
                            }
                        }
                        // Entries successful loaded
                        flag_LoadedFromFile = true;
                        flag_ChangedSinceLoad = false;
                        memory_LoadedFile = sFilename;
                        return true;
                    }
                    else {
                        // Empty file successful loaded
                        flag_LoadedFromFile = true;
                        flag_ChangedSinceLoad = false;
                        memory_LoadedFile = sFilename;
                        return true;
                    }
                }
                else {
                    return false;
                }
            }
            else {
                return false;
            }
        }

        private bool do_Settings_Save(string sFilename) {
            FileInfo oFInfo;
            FileStream oStream = null;
            StreamWriter oWriter = null;

            oFInfo = new FileInfo(sFilename);

            if (oFInfo.Exists) { oFInfo.Delete(); }
            try {
                oStream = new FileStream(sFilename, FileMode.OpenOrCreate);
                oWriter = new StreamWriter(oStream);
                for (int i = 0; i < lList.Count; i++) {
                    oWriter.WriteLine(lList[i][0] + "=" + lList[i][1]);
                }
                oWriter.Close();
                oStream.Close();
            }
            catch (Exception eX1) {
                try {
                    oWriter.Close();
                    oStream.Close();
                }
                catch (Exception eX2) {

                }
                return false;
            }
            flag_ChangedSinceSave = false;
            return true;
        }

        private bool do_Setting_Set(string sName, string sValue) {
            if ((sName == null) || (sName == "") || (sValue == null)) { return false; }
            for (int i = 0; i < lList.Count; i++) {
                if (lList[i][0].ToLower() == sName.ToLower()) {
                    if (lList[i][1] != sValue) { flag_ChangedSinceLoad = true; flag_ChangedSinceSave = true; }
                    lList[i] = new string[] { sName, sValue };
                    return true;
                }
            }
            lList.Add(new string[] { sName, sValue });
            flag_ChangedSinceLoad = true;
            flag_ChangedSinceSave = true;
            return true;
        }

        private string do_Setting_Get(string sName) {
            if ((sName == null) || (sName == "")) { return null; }
            if ((memory_LastSettingQuery != null) && (memory_LastSettingQuery[0] == sName)) { return memory_LastSettingQuery[1]; }
            for (int i = 0; i < lList.Count; i++) {
                if (lList[i][0].ToLower() == sName.ToLower()) {
                    memory_LastSettingQuery = lList[i];
                    return lList[i][1];
                }
            }
            return null;
        }

        private bool do_Setting_Delete(string sName) {
            if ((sName == null) || (sName == "")) { return false; }
            for (int i = 0; i < lList.Count; i++) {
                if (lList[i][0].ToLower() == sName.ToLower()) {
                    lList.RemoveAt(i);
                    flag_ChangedSinceLoad = true;
                    flag_ChangedSinceSave = true;
                    return true;
                }
            }
            return false;
        }

        #endregion

    }
}
